#pragma once 
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <queue>

class SafeQue
{
    public:
        SafeQue()
        {
            capacity = 2;
            sem_init(&lock, 0, 1);
            sem_init(&producer, 0, capacity);
            sem_init(&consumer, 0, 0);
        }

        ~SafeQue()
        {}
    
    public:
        void Push(int val, int who)
        {
            sem_wait(&producer);
            //保证互斥
            sem_wait(&lock);
            
            que.push(val);
            printf("i am producer %d, i produce %d\n", who, val);

            //先解锁再唤醒，先唤醒再解锁没有意义，因为锁都还在别人手里
            sem_post(&lock);
            sem_post(&consumer);
        }

        int Pop(int who)
        {
            sem_wait(&consumer);
            sem_wait(&lock);
            
            int ret = que.front();
            que.pop();
            printf("i am consumer %d, i consume %d\n", who, ret);

            sem_post(&lock);
            sem_post(&producer);
            return ret;
        }
    private:
        int capacity;
        std::queue<int> que;
        sem_t lock;
        sem_t producer;
        sem_t consumer;
};
